package com.nf.dbutils;

import javax.sql.DataSource;
import java.sql.*;

public abstract class AbstractSqlExecutor {
    /**
     * 子类不要直接使用此字段，应该用
     */
    protected DataSource dataSource;

    /**
     * 无参的构造函数是用户提供Connection连接的方式来使用我们的库
     */
    public AbstractSqlExecutor() {
    }

    public AbstractSqlExecutor(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public DataSource getDataSource(){
        return dataSource;
    }

    /**
     * 这个方法是为了让子类可以重写此方法，以便对DataSource返回的Connection有额外的设置
     * protected受保护的，为了给子类重写，所以不用public公用的
     * @return
     */
    protected Connection prepareConnection(){
        try {
            return getDataSource().getConnection();
        } catch (SQLException e) {
            throw new DaoExecutor("从DataSource创建Connection失败！");
        }
    }

    protected void fillStatement(PreparedStatement stmt,Object... params) throws SQLException {
//        判断参数，为空直接返回给你
        if (params==null){
            return;
        }
        for (int i = 0; i < params.length; i++) {
//            循环遍历后还为空就转换成sql可读的空，不为空就直接给过去
            if (params[i]!=null){
                stmt.setObject(i+1,params[i]);
            }else {
                stmt.setNull(i+1, Types.VARCHAR);
            }
        }
    }

    protected void checkSql(Connection conn,boolean closeConn,String sql){
//        走到判断，已经表示conn连接不为null空了
//        判断sql是否为空
        if (sql==null||sql.trim().length()==0){
//          不为sql空后，才会帮你关闭连接
            if (closeConn){
                ResourceCleanerUtils.closeQuietly(conn);
            }
            throw new DaoExecutor("sql语句不能为空！");
        }
    }

    /**
     * 下面代码有一个专门的称呼：guard code 守护代码
     * @param conn
     */
    protected void checkConnection(Connection conn){
        if (conn==null){
            throw new DaoExecutor("没有连接！");
        }
    }

    protected void checkResultSetHandler(ResultSetHandler handler,boolean closeConn,Connection conn){
        if (handler==null){
            if (closeConn){
                ResourceCleanerUtils.closeQuietly(conn);
            }
            throw new DaoExecutor("resultSet handler 结果集必须有，查询才能处理");
        }
    }

    protected void close(Connection conn){
        ResourceCleanerUtils.closeQuietly(conn);
    }

    protected void close(ResultSet rs){
        ResourceCleanerUtils.closeQuietly(rs);
    }

    protected void close(PreparedStatement stmt){
        ResourceCleanerUtils.closeQuietly(stmt);
    }
}
